import time
import frida
import base64
import json
import sys
import threading
import tkinter as tk
import subprocess
import check_frida
import submit_model


def adb_draw_symbol(symbol):
    """根据符号选择进行 ADB 输入绘制"""
    try:
        adb_command = None
        if symbol == '>':
            adb_command = 'adb shell "input swipe 500 1210 520 1190 0 && input swipe 520 1190 500 1170 0"'
        elif symbol == '<':
            adb_command = 'adb shell "input swipe 510 1210 490 1190 0 && input swipe 490 1190 510 1170 0"'
        elif symbol == '=':
            adb_command = 'adb shell "input swipe 400 740 430 740 0 && input swipe 400 760 430 760 0"'
        elif symbol == '1':
            adb_command = 'adb shell "input swipe 400 720 400 740 0"'
            subprocess.run(adb_command, shell=True, check=True)
            # subprocess.run(adb_command, shell=True, check=True)
        subprocess.run(adb_command, shell=True, check=True)
    except subprocess.CalledProcessError as e:
        print(f"ADB 命令执行失败: {e}. 尝试重新连接设备...")
        adb_connect_device()


def adb_connect_device():
    """重连到设备"""
    try:
        adb_command = "adb connect 127.0.0.1:16384"
        subprocess.run(adb_command, shell=True, check=True)
        return True
    except subprocess.CalledProcessError as e:
        print(f"ADB 命令执行失败: {e}. 连接设备失败...")


def restart_pk():
    time.sleep(6)
    print("领取奖励")
    adb_command = 'adb shell "input tap 550 1450"'
    subprocess.run(adb_command, shell=True, check=True)
    time.sleep(1)
    print("开始下一轮pk")
    adb_command = 'adb shell "input tap 750 1850"'
    subprocess.run(adb_command, shell=True, check=True)
    time.sleep(2)
    adb_command = 'adb shell "input tap 550 1700"'
    subprocess.run(adb_command, shell=True, check=True)


def select_answer(answer):
    """选择正确的答案并写入文件"""
    select_answer_list = []

    with open("answer.txt", "w") as f:
        for question in answer["examVO"]["questions"]:
            correct_answer = next(
                (ans for ans in question["answers"] if "." in ans),
                question["answers"][0]
            )

            select_answer_list.append(correct_answer)
            # print(correct_answer, end="  ")
            f.write(correct_answer + "  ")

    q_num = len(select_answer_list)
    threading.Thread(target=auto_pk, args=(select_answer_list, q_num,)).start()


def gui_answer(answers, q_num):
    """GUI 继续按钮，点击后执行答案输入"""
    print(f"等待开始对局！！！ 共{q_num}道题")
    root = tk.Tk()
    root.title("继续执行")

    def on_button_click():
        for answer in answers:
            adb_draw_symbol(answer)
            time.sleep(0.3)
        root.destroy()

    button = tk.Button(root, text="点击继续", command=on_button_click)
    button.pack(pady=20)

    root.mainloop()


def countdown_timer(seconds):
    """倒计时函数，每秒更新一次"""
    for remaining in range(seconds, 0, -1):
        sys.stdout.write(f"\r倒计时: {remaining} 秒")
        sys.stdout.flush()
        time.sleep(1)
    print("\r倒计时结束！准备开始对局。\n")


def auto_pk(answers, q_num):
    print(f"等待开始对局！！！ 共{q_num}道题")
    print(f"本次pk的答案：{answers}")
    # 添加12秒倒计时
    countdown_timer(13)
    for answer in answers:
        adb_draw_symbol(answer)
        time.sleep(0.35)
    restart_pk()


def on_message(message, data, match_script, q_num, del_topic, auto_answer):
    """处理来自 JS 的消息"""
    if message['type'] == 'send':
        encoded_data = message['payload']
        # print("[JS] Received Base64: {}".format(encoded_data))
        # 删除所有换行符
        cleaned_string = encoded_data.replace("\n", "")
        # 解码Base64
        result = base64.b64decode(cleaned_string).decode('utf-8')
        data = json.loads(result)

        c_results = data
        # 秒杀
        if del_topic:
            kill_result = skill_pk(data, q_num)
            c_results = w_answers(kill_result)
        if auto_answer:
            select_answer(c_results)

        result = json.dumps(data, ensure_ascii=False)
        result_makebase64 = base64.b64encode(result.encode('utf-8')).decode('utf-8')
        if not isinstance(result_makebase64, str):
            result_makebase64 = str(result_makebase64)
        match_script.post({'type': 'input', 'payload': result_makebase64})
    else:
        print("[{}] {}".format(message['type'], message['description']))


# 秒杀模块
def skill_pk(data, q_num):
    if 'examVO' in data and 'questions' in data['examVO']:
        # data['examVO']['questionCnt'] = 10
        data['examVO']['questions'] = data['examVO']['questions'][:q_num]  # 只保留第一道题目
    return data


def w_answers(data):
    if 'examVO' in data and 'questions' in data['examVO']:
        for question in data['examVO']['questions']:
            question['answer'] = '1'  # 将 answers 设置为空列表
            question['answers'] = ['1']
    return data


def get_pid_from_adb(package_name):
    try:
        result = subprocess.run(['adb', 'shell', 'ps | grep ' + package_name],
                                capture_output=True, text=True)
        output = result.stdout.strip()
        if output:
            g_pid = int(output.split()[1])
            print(f"通过 adb 找到 PID: {g_pid}")
            return g_pid
        else:
            print("adb 没有找到该应用的 PID")
            return None
    except Exception as e:
        print(f"adb 获取 PID 时出错: {e}")
        return None


def start_app(package_name, activity_name):
    """通过 adb 命令启动指定应用"""
    try:
        # 使用 adb 命令启动应用
        adb_command = f'adb shell am start -n {package_name}/{activity_name}'
        subprocess.run(adb_command, shell=True, check=True)
        print(f"应用 {package_name} 成功启动！")
    except subprocess.CalledProcessError as e:
        print(f"启动应用时出错: {e}")


def start_frida_session(s_pid, q_num, del_topic, auto_answer):
    """启动 Frida session 并加载 JS 脚本"""
    device = frida.get_usb_device()
    session = device.attach(s_pid)
    with open("js/do_matchV2_byDataDecryptCommand_model.js", encoding='utf-8') as f:
        js_script = session.create_script(f.read())
    js_script.on('message', lambda msg, data: on_message(msg, data, js_script, q_num, del_topic, auto_answer))
    js_script.load()
    return js_script


if __name__ == "__main__":
    # 删除题目及修改答案选项
    d_topic = True
    num = 5 # 保留题目数量
    # 自动答题选项
    a_answer = False

    adb_flag = adb_connect_device()
    if adb_flag:
        check_frida.start_frida_server()
        pid = get_pid_from_adb("com.fenbi.android.leo")
        if pid is None:
            start_app("com.fenbi.android.leo", ".activity.RouterActivity")
            print("小猿口算——启动！")
            time.sleep(3)
            new_pid = get_pid_from_adb("com.fenbi.android.leo")
            script = start_frida_session(new_pid, num, d_topic, a_answer)
            # 此脚本用于修改提交的答题的时间，不修改请注释掉
            s_script = submit_model.modify_exam_answers(new_pid)
            # 保持脚本运行
            sys.stdin.read()
        else:
            script = start_frida_session(pid, num, d_topic, a_answer)
            # 此脚本用于修改提交的答题的时间，不修改请注释掉
            s_script = submit_model.modify_exam_answers(pid)
            # 保持脚本运行
            sys.stdin.read()
